import * as redis from 'redis';

export class CacheClient {
  client: any;

  initialize(
    option: {host: string; port: number; password: string; database: string} = {
      host: 'localhost',
      port: 6379,
      password: '',
      database: ''
    }
  ): void {
    const client = redis.createClient(option);

    client.on('connect', () => {
      return console.log('redis connected!');
    });

    if (option.database) {
      client.select(option.database);
    }

    client.on('error', err => {
      console.log('Error ' + err);
    });

    this.client = client;
  }

  set(type: string, key: string, value: any): Promise<void> {
    return new Promise<void>((resolve, reject) => {
      this.client.set(type + ':' + key, JSON.stringify(value), (err, reply) => {
        if (err) {
          reject(err);
        }
        resolve();
      });
    });
  }

  setex(type: string, key: string, seconds: number, value: any): Promise<void> {
    return new Promise<void>((resolve, reject) => {
      this.client.setex(type + ':' + key, seconds, JSON.stringify(value), (err, reply) => {
        if (err) {
          reject(err);
        }
        resolve();
      });
    });
  }

  get(type: string, key: string): Promise<any> {
    return new Promise<any>((resolve, reject) => {
      this.client.get(type + ':' + key, (err, reply) => {
        if (err) {
          reject(err);
        }
        if (reply) {
          const o = JSON.parse(reply);
          resolve(o);
        } else {
          resolve(null);
        }
      });
    });
  }

  del(type: string, key: string): Promise<void> {
    return new Promise((resolve, reject) => {
      this.client.del(type + ':' + key, (err, reply) => {
        if (err) {
          reject(err);
        }
        resolve();
      });
    });
  }

  expire(type: string, key: string, seconds: number): Promise<void> {
    return new Promise<void>((resolve, reject) => {
      this.client.expire(type + ':' + key, seconds, (err, reply) => {
        if (err) {
          reject(err);
        }
        resolve(reply);
      });
    });
  }

  mget(type: string, keys: string[]): Promise<any[]> {
    return new Promise<[any]>((resolve, reject) => {
      const typeKeys = [];
      keys.forEach(key => {
        typeKeys.push(type + ':' + key);
      });
      this.client.mget(typeKeys, (err, replies) => {
        if (err) {
          reject(err);
        }

        if (replies != null) {
          const objects = [];
          replies.forEach(reply => {
            const o = JSON.parse(reply);
            objects.push(o);
          });
          // resolve(objects);
        } else {
          resolve(null);
        }
      });
    });
  }
}

const defaultCacheClient = new CacheClient();

export default defaultCacheClient;
